using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class BattleAnimationComponent : TComponent
    {
        public UnitView unit;
        public bool enable { get; private set; }
        
        private UnitViewComponent unitComp;
        public Animator animator => this.unitComp.animator;
        // timeline播放动作时，会覆盖当前动作，若当前仍在播放会导致动作无法衔接，用重置controller的方法来确保timeline结束后的动作从第一帧开始
        private RuntimeAnimatorController defaultController;

        private List<(int, bool)> paramBoolCache = new List<(int, bool)>();
        private List<(int, float)> paramFloatCache = new List<(int, float)>();

        private float curSpeed;
        
        protected override void OnDispose()
        {
            this.defaultController = null;
        }

        public override void OnCreate(TEntity entity)
        {
            this.unit = (UnitView)entity;
        }

        public void Initialize()
        {
            this.unitComp = this.unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            // var rViewComp = this.unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            // var rModelTrans = rViewComp.transform.Find("model");
            // if (rModelTrans)
            // {
            //     // this.animator = rModelTrans.GetComponent<Animation>();
            // }
            if (this.animator)
            {
                this.defaultController = this.animator.runtimeAnimatorController;
            }
        }

        public void Enable(bool born = false)
        {
            this.enable = true;
            if (this.animator && this.defaultController != null)
            {
                this.animator.runtimeAnimatorController = this.defaultController;
            }
            for (int i = 0; i < this.paramBoolCache.Count; i++)
            {
                var rItem = this.paramBoolCache[i];
                this.animator.SetBool(rItem.Item1, rItem.Item2);
            }
            this.paramBoolCache.Clear();
            for (int i = 0; i < this.paramFloatCache.Count; i++)
            {
                var rItem = this.paramFloatCache[i];
                this.animator.SetFloat(rItem.Item1, rItem.Item2);
            }
            this.paramFloatCache.Clear();

            if (born)
            {
                this.SetTrigger(AnimationConst.Param_Born);
            }
        }

        public void Disable()
        {
            this.enable = false;
            this.animator.runtimeAnimatorController = null;
        }

        public void PlayAnime(int nHash)
        {
#if UNITY_EDITOR

            if (!Application.isPlaying)
            {
                this.animator.Play(nHash);
            }
            else
#endif
            if (this.animator && this.animator.runtimeAnimatorController != null)
            {
                this.animator.CrossFade(nHash, 0.2f);
            }
        }

        public void SetTrigger(int nHash)
        {
            if (this.animator && this.animator.runtimeAnimatorController != null)
            {
                this.animator.SetTrigger(nHash);
            }
        }

        private void SetBool(int hash, bool value)
        {
            if (!this.enable)
            {
                this.paramBoolCache.Add((hash, value));
            }
            else if (this.animator && this.animator.runtimeAnimatorController != null)
            {
                this.animator.SetBool(hash, value);
            }
        }

        private void SetFloat(int hash, float value)
        {
            if (!this.enable)
            {
                this.paramFloatCache.Add((hash, value));
            }
            else if (this.animator && this.animator.runtimeAnimatorController != null)
            {
                this.animator.SetFloat(hash, value);
            }
        }

        public void SetAnimeSpeed(float speed)
        {
            if (this.curSpeed <= 0 || Math.Abs(this.curSpeed - speed) > 0.005f)
            {
                this.curSpeed = speed;
                if (this.curSpeed < 0.01f)
                {
                    this.curSpeed = 0;
                }
                this.SetFloat(AnimationConst.Param_Speed, this.curSpeed);
            }
        }

        public void Relive()
        {
            if (this.animator && this.animator.runtimeAnimatorController != null)
            {
                this.animator.ResetTrigger(AnimationConst.Param_Die);
                this.animator.Play(AnimationConst.Name_StandMove);
            }
        }

        public void SetCharge(bool bInCharge)
        {
            this.SetBool(AnimationConst.Param_Charge, bInCharge);
        }
        
        public void SetRush(bool bInCharge)
        {
            this.SetBool(AnimationConst.Param_Rush, bInCharge);
        }
    }
}